#ifndef _ASSETSLOADER_H_
#define _ASSETSLOADER_H_

#include <unordered_map>
#include <string>
#include <functional>
#include <SEAssets/AssetsElem.h>
#include <SECore/StaticString.h>
#include <SECore/Util.h>
#include <map>

namespace SEngine
{
    class TextureHDR;
    class Texture;
    class ScriptState;
    class MeshFilter;
    class Material;
    class Shader;
    using AssetsAllTypes = TypesLoader<
        TextureHDR,
        Texture,
        ScriptState,
        MeshFilter,
        Material,
        Shader
    >;

    template<typename T>
    struct AssetsTypeStr {};
    template<>
    struct AssetsTypeStr<TextureHDR> { static constexpr char * name = "TEXTUREHDR"; };
    template<>
    struct AssetsTypeStr<Texture> { static constexpr char * name = "TEXTURE"; };
    template<>
    struct AssetsTypeStr<ScriptState> { static constexpr char * name = "SCRIPT"; };
    template<>
    struct AssetsTypeStr<MeshFilter> { static constexpr char * name = "MESH"; };
    template<>
    struct AssetsTypeStr<Material> { static constexpr char * name = "MATERIAL"; };
    template<>
    struct AssetsTypeStr<Shader> { static constexpr char * name = "SHADER"; };

    class AssetsLoader
    {
    public:
        using LoaderFn = std::function<void(void)>;
        using LoaderTable = std::unordered_map<std::string, std::function<void(AssetsElem&, const std::string&)>>;
    public:
        AssetsLoader(const std::string & rootPath = "");
        virtual ~AssetsLoader() = default;
        int ScanFileTree(AssetsElem & rootElem, const std::string & rootPath, std::function<void(AssetsElem&, LoaderTable&)> && fn);
        int ForeachFileTree(AssetsElem & curElem, std::function<void(AssetsElem&)> && fn);
        
        static std::string RelativelyPath(std::string rootPath, std::string absPath);
        
    private:
        int ScanFileTreeImpl(AssetsElem & curElem, const std::string & curPath, std::function<void(AssetsElem&, LoaderTable&)> && fn, std::multimap<int, LoaderFn> & loaderTasks);
        bool IsSupportAsset(const std::string &path);
        
    private:
        std::string m_rootPath;
        static LoaderTable s_assetsLoaderTable;
        // static std::unordered_map<std::string, std::string> s_assetsTypeTable;
    };
} // namespace SEngine


#endif